"""Command handler for voice_assistant_contro."""
from __future__ import annotations

import json
import logging
from typing import Any, Callable, Dict, List, Optional
from enum import Enum

from homeassistant.core import HomeAssistant

_LOGGER = logging.getLogger(__name__)

class StandardFanMode(str, Enum):
    """标准化的风速模式枚举"""
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    AUTO = "auto"

class CommandHandler:
    """处理来自 WebSocket 的命令."""

    # 风速模式映射配置
    FAN_MODE_MAPPINGS = {
        # 数字档位映射
        "numeric": {
            "1": StandardFanMode.LOW,
            "2": StandardFanMode.MEDIUM,
            "3": StandardFanMode.HIGH,
            "auto": StandardFanMode.AUTO,
        },
        # 中文档位映射
        "chinese": {
            "低": StandardFanMode.LOW,
            "中": StandardFanMode.MEDIUM,
            "高": StandardFanMode.HIGH,
            "自动": StandardFanMode.AUTO,
        },
        # 英文档位映射
        "english": {
            "low": StandardFanMode.LOW,
            "medium": StandardFanMode.MEDIUM,
            "high": StandardFanMode.HIGH,
            "auto": StandardFanMode.AUTO,
        }
    }

    def __init__(
        self, 
        hass: HomeAssistant, 
        entities: list[str],
        send_message_callback: Callable,
        auth_state_callback: Callable[[bool], None] | None = None,
    ) -> None:
        """初始化命令处理器."""
        self.hass = hass
        self.entities = entities
        self._send_message = send_message_callback
        self._auth_state_callback = auth_state_callback
        self._device_fan_modes: Dict[str, List[str]] = {}

    def _detect_fan_mode_type(self, fan_modes: List[str]) -> Optional[str]:
        """检测风速模式类型"""
        if not fan_modes:
            return None
        
        # 检查第一个模式来判断类型
        first_mode = fan_modes[0].lower()
        
        # 检查是否是数字类型
        if any(mode.isdigit() for mode in fan_modes):
            return "numeric"
        # 检查是否包含中文
        elif any('\u4e00' <= char <= '\u9fff' for char in ''.join(fan_modes)):
            return "chinese"
        # 默认为英文
        else:
            return "english"

    def _standardize_fan_mode(self, entity_id: str, fan_mode: str) -> str:
        """将设备的风速模式转换为标准模式"""
        if entity_id not in self._device_fan_modes:
            # 获取设备支持的风速模式
            state = self.hass.states.get(entity_id)
            if state and "fan_modes" in state.attributes:
                self._device_fan_modes[entity_id] = state.attributes["fan_modes"]
                _LOGGER.info("设备 %s 支持的风速模式: %s", entity_id, self._device_fan_modes[entity_id])
            else:
                _LOGGER.warning("无法获取设备 %s 的风速模式", entity_id)
                return fan_mode

        # 检测设备风速模式类型
        mode_type = self._detect_fan_mode_type(self._device_fan_modes[entity_id])
        if not mode_type:
            return fan_mode

        # 转换为标准模式
        mapping = self.FAN_MODE_MAPPINGS.get(mode_type, {})
        return mapping.get(fan_mode, fan_mode)

    def _convert_to_device_fan_mode(self, entity_id: str, standard_mode: str) -> str:
        """将标准风速模式转换为设备实际的风速模式"""
        if entity_id not in self._device_fan_modes:
            return standard_mode

        mode_type = self._detect_fan_mode_type(self._device_fan_modes[entity_id])
        if not mode_type:
            return standard_mode

        # 反向查找映射
        mapping = self.FAN_MODE_MAPPINGS.get(mode_type, {})
        for device_mode, std_mode in mapping.items():
            if std_mode == standard_mode and device_mode in self._device_fan_modes[entity_id]:
                return device_mode

        return standard_mode

    async def handle_message(self, data: dict[str, Any]) -> None:
        """处理收到的 WebSocket 消息."""
        msg_type = data.get("type")
        _LOGGER.info("msg_type: %s", msg_type)
        if msg_type == "pong":
            return
            
        if msg_type == "query_state":
            await self._handle_query_state(data)
        elif msg_type == "query_all_states":
            await self._handle_query_all_states(data)
        elif msg_type == "control":
            await self._handle_control(data)
        elif msg_type == "call_service":
            await self._handle_call_service(data)
        elif msg_type == "connected":
            # 处理服务器认证完成消息
            if self._auth_state_callback:
                self._auth_state_callback(True)
            _LOGGER.info("服务器认证完成")
        else:
            _LOGGER.warning("收到未知消息类型: %s", msg_type)

    async def _handle_query_state(self, data: dict[str, Any]) -> None:
        """处理状态查询请求."""
        message_id = data.get("message_id", "")  # 提供默认值避免 None
        entity_id = data.get("data", {}).get("entity_id")
        
        if not entity_id:
            await self._send_error_response(
                message_id,
                "invalid_request",
                "缺少 entity_id 参数"
            )
            return
        _LOGGER.warning("授权实体: %s", json.dumps(self.entities))
        # 检查实体是否在允许列表中
        if entity_id not in self.entities:
            _LOGGER.warning("收到未授权实体的查询: %s", entity_id)
            await self._send_error_response(
                message_id, 
                "unauthorized_entity",
                f"实体 {entity_id} 未授权"
            )
            return
            
        # 获取实体状态
        state = self.hass.states.get(entity_id)
        if not state:
            await self._send_error_response(
                message_id,
                "entity_not_found",
                f"未找到实体 {entity_id}"
            )
            return
        
        # 对climate设备的fan_mode进行标准化映射
        attributes = dict(state.attributes)
        if state.domain == "climate" and "fan_mode" in attributes:
            attributes["fan_mode"] = self._standardize_fan_mode(entity_id, attributes["fan_mode"])
        
        # 发送状态响应
        try:
            await self._send_message({
                "type": "state_response",
                "message_id": message_id,
                "data": {
                    "entity_id": entity_id,
                    "state": state.state,
                    "attributes": attributes,
                }
            })
        except Exception as err:
            _LOGGER.error("发送状态响应失败: %s", err)

    async def _handle_query_all_states(self, data: dict[str, Any]) -> None:
        """处理所有授权实体状态查询请求."""
        message_id = data.get("message_id", "")
        states = []
        for entity_id in self.entities:
            state = self.hass.states.get(entity_id)
            if state:
                states.append({
                    "entity_id": entity_id,
                    "state": state.state,
                    "attributes": dict(state.attributes),
                })
        _LOGGER.warning("all_states_response: %s", json.dumps(states))
        try:
            await self._send_message({
                "type": "all_states_response",
                "message_id": message_id,
                "data": {
                    "states": states
                }
            })
        except Exception as err:
            _LOGGER.error("发送所有状态响应失败: %s", err)

    async def _handle_control(self, data: dict[str, Any]) -> None:
        """处理控制命令."""
        entity_id = data.get("data", {}).get("entity_id")
        
        if not entity_id:
            if "message_id" in data:
                await self._send_error_response(
                    data["message_id"],
                    "invalid_request",
                    "缺少 entity_id 参数"
                )
            return
        _LOGGER.warning("授权实体: %s", json.dumps(self.entities))
        
        # 检查实体是否在允许列表中
        if entity_id not in self.entities:
            _LOGGER.warning("收到未授权实体的控制命令: %s", entity_id)
            if "message_id" in data:
                await self._send_error_response(
                    data["message_id"],
                    "unauthorized_entity",
                    f"实体 {entity_id} 未授权"
                )
            return
            
        domain = data.get("data", {}).get("domain")
        service = data.get("data", {}).get("service")
        service_data = data.get("data", {}).get("service_data", {})
        
        if not domain or not service:
            if "message_id" in data:
                await self._send_error_response(
                    data["message_id"],
                    "invalid_request",
                    "缺少 domain 或 service 参数"
                )
            return
        
        # 调用服务
        try:
            await self.hass.services.async_call(
                domain,
                service,
                {"entity_id": entity_id, **service_data},
                blocking=True,
            )
            
            # 发送控制响应
            if "message_id" in data:
                await self._send_message({
                    "type": "control_response",
                    "message_id": data["message_id"],
                    "data": {
                        "success": True,
                        "message": "success"
                    }
                })
        except Exception as err:
            _LOGGER.error("执行控制命令失败: %s", err)
            if "message_id" in data:
                await self._send_error_response(
                    data["message_id"],
                    "control_failed",
                    str(err)
                )

    async def _handle_call_service(self, data: dict[str, Any]) -> None:
        """处理服务调用请求."""
        message_id = data.get("message_id", "")
        service_data = data.get("data", {})
        
        domain = service_data.get("domain")
        service = service_data.get("service")
        target = service_data.get("target", {})
        service_params = service_data.get("service_data", {})

        if not domain or not service:
            await self._send_error_response(
                message_id,
                "invalid_request",
                "缺少 domain 或 service 参数"
            )
            return

        # 检查是否是风速模式设置
        if domain == "climate" and service == "set_fan_mode":
            entity_id = target.get("entity_id")
            if entity_id:
                # 转换风速模式
                fan_mode = service_params.get("fan_mode")
                if fan_mode:
                    service_params["fan_mode"] = self._convert_to_device_fan_mode(entity_id, fan_mode)
                    _LOGGER.info("转换风速模式 %s -> %s", fan_mode, service_params["fan_mode"])

        try:
            # 调用请求的服务
            await self.hass.services.async_call(
                domain,
                service,
                {**service_params, **target},
                blocking=True,
            )
            
            # 发送成功响应
            await self._send_message({
                "type": "call_service_response",
                "message_id": message_id,
                "data": {
                    "success": True,
                    "message": "success"
                }
            })
        except Exception as err:
            _LOGGER.error("服务调用失败: %s", err)
            await self._send_error_response(
                message_id,
                "service_call_failed",
                str(err)
            )

    async def _send_error_response(self, message_id: str, code: str, message: str) -> None:
        """发送错误响应到服务器."""
        try:
            await self._send_message({
                "type": "error_response",
                "message_id": message_id,
                "data": {
                    "code": code,
                    "message": message
                }
            })
        except Exception as err:
            _LOGGER.error("发送错误响应失败: %s", err)

    async def send_state_update(self, entity_id: str, state: str, attributes: dict) -> None:
        """发送状态更新到服务器."""
        # 只发送允许的实体状态更新
        if entity_id not in self.entities:
            return
            
        # 标准化风速模式
        if "fan_mode" in attributes:
            attributes["fan_mode"] = self._standardize_fan_mode(entity_id, attributes["fan_mode"])
            
        try:
            await self._send_message({
                "type": "state_update",
                "data": {
                    "entity_id": entity_id,
                    "state": state,
                    "attributes": attributes
                }
            })
        except Exception as err:
            _LOGGER.error("发送状态更新失败: %s", err) 